home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 11 / Cream of the Crop 11-1.iso / games / ted5.zip / IGRABSRC.ZIP / LBMLOAD.BAK < prev    next >
Text File  |  1993-02-04  |  13KB  |  566 lines

  1. /////////////////////////////////////////////////////////////
  2. /*
  3. ** ILBM file loader by John Romero (C) 1991 Id Software
  4. **
  5. ** Loads and decompresses an ILBM-format file to the
  6. ** screen in either CGA, EGA or MCGA -- compressed or
  7. ** or unpacked!
  8. **
  9. ** Merely pass the filename of the image to LoadLBM
  10. ** and sit back! The proper graphics mode is initialized
  11. ** and the screen (or brush) is loaded and displayed!
  12. **
  13. */
  14. /////////////////////////////////////////////////////////////
  15. #include "igrab.h"
  16. #pragma hdrstop
  17.  
  18. //
  19. // LBMload PROTOs
  20. //
  21.  
  22. void GetChunkID(char huge *buffer,char *tempstr);
  23. int  NextChunkID(char huge *buffer);
  24. void huge *Decompress(char huge *buffer,char *unpacked,int bpwidth,char planes);
  25. void huge *SetupLBM(char *filename);
  26. void Do_CGA_Screen(char huge *buffer,char compress,char planes,int width,int height,char huge *scrnmem);
  27. void Do_EGA_Screen(char huge *buffer,char compress,char planes,int width,int height,char huge *scrnmem);
  28. void Do_MCGA_Screen(char huge *buffer,char compress,int width,int height,char huge *scrnmem);
  29.  
  30. char typestr[5],huge *startbuff;
  31.  
  32.  
  33. //
  34. // Here goes!
  35. //
  36. char huge *LoadLBM(char *filename,LBMtype *thelbm)
  37. {
  38.  char huge *buffer,huge *cmap,huge *scrnmem;
  39.  char planes,tempstr[5],compress;
  40.  unsigned handle,width,height;
  41.  
  42.   if((buffer = SetupLBM(filename))==NULL) errout("LBMLOAD error");
  43.  
  44.   /*
  45.   ** Need to get BMHD info, like:
  46.   ** - screen width, height
  47.   ** - # of bitplanes
  48.   ** - compression flag (YES/NO)
  49.   */
  50.  
  51.   width  = (*(buffer+9)&0xFF)+(*(buffer+8)*256);
  52.   height = (*(buffer+11)&0xFF)+(*(buffer+10)*256);
  53.   planes = *(buffer+16);
  54.   if (buffer[17])
  55.     {
  56.      char string[]="The ILBM screen '";
  57.  
  58.      strcat(string,filename);
  59.      strcat(string,"' is in STENCIL mode!\nGo back into DeluxePaint and turn it off!");
  60.      errout(string);
  61.     }
  62.   compress = *(buffer+18);
  63.  
  64.   thelbm->width=width;    // fill the struct
  65.   thelbm->height=height;
  66.   thelbm->planes=planes;
  67.  
  68.   if ((scrnmem=(char huge *)farmalloc((long)(width/8)*height*planes))==NULL)
  69.     {
  70.      char str[100]="Not enough memory for loading the ILBM screen '";
  71.  
  72.      strcat(str,filename);
  73.      strcat(str,"'!");
  74.      errout(str);
  75.     }
  76.  
  77.   /*
  78.   ** Find the CMAP chunk so I can remap the registers...
  79.   */
  80.  
  81.   movedata(FP_SEG(buffer),FP_OFF(buffer),_DS,(unsigned)tempstr,4);
  82.   tempstr[4]=0;
  83.   while (strcmp(tempstr,"CMAP")!=0)
  84.      {
  85.       buffer += NextChunkID(buffer);
  86.       movedata(FP_SEG(buffer),FP_OFF(buffer),_DS,(unsigned)tempstr,4);
  87.      }
  88.  
  89.   cmap = buffer+8;
  90.  
  91.   /*
  92.   ** Now, find the BODY chunk...
  93.   */
  94.  
  95.   movedata(FP_SEG(buffer),FP_OFF(buffer),_DS,(unsigned)tempstr,4);
  96.   while (strcmp(tempstr,"BODY")!=0)
  97.      {
  98.       buffer += NextChunkID(buffer);
  99.       movedata(FP_SEG(buffer),FP_OFF(buffer),_DS,(unsigned)tempstr,4);
  100.      }
  101.  
  102.   /*
  103.   ** Found the BODY chunk! Here we go!
  104.   */
  105.  
  106.   buffer += 8; /* point to actual data */
  107.  
  108.   switch (planes)
  109.     {
  110.       case 2: Do_CGA_Screen(buffer,compress,planes,width,height,scrnmem);
  111.           break;
  112.       case 4: Do_EGA_Screen(buffer,compress,planes,width,height,scrnmem);
  113.           break;
  114.       case 8: {
  115.            unsigned int i;
  116.  
  117.            if (!noshow)
  118.          {
  119.           for (i=0;i<0x300;i++) (unsigned char)*cmap++ >>= 2;
  120.  
  121.           cmap -= 0x300; // reset to beginning again
  122.  
  123.           _BX = 0;
  124.           _CX = 0x100;
  125.           _ES = FP_SEG(cmap);
  126.           _DX = FP_OFF(cmap);
  127.           _AX = 0x1012;
  128.           geninterrupt(0x10);
  129.          }
  130.  
  131.            Do_MCGA_Screen(buffer,compress,width,height,scrnmem);
  132.  
  133.            break;
  134.           }
  135.  
  136.       default: {
  137.         char msg[80]="This screen has ",temp[10];
  138.  
  139.         itoa(planes,temp,10);
  140.         strcat(msg,temp);
  141.         strcat(msg," bitplanes. I don't unnerstand that sorta stuff.");
  142.         errout(msg);
  143.            }
  144.     }
  145.   farfree((void far *)startbuff);
  146.  return scrnmem;
  147. }
  148.  
  149.  
  150. void huge *SetupLBM(char *filename)
  151. {
  152.  long filesize;
  153.  int handle;
  154.  char huge *buffer;
  155.  char tempstr[64];
  156.  
  157.  
  158.  
  159.  filesize = filelen(filename);
  160.  buffer = startbuff = (char huge *)farmalloc(filesize);
  161.  if (buffer==NULL)
  162.    errout("Not enough memory to load ILBM file!");
  163.  
  164.  strupr(filename);
  165.  if (strstr(filename,".")==NULL)
  166.     strcat(filename,".LBM");
  167.  
  168.  if (access(filename,0))
  169.    {
  170.     char msg[80]="The ILBM file '";
  171.  
  172.     strcat(msg,filename);
  173.     strcat(msg,"' doesn't exist!");
  174.     errout(msg);
  175.    }
  176.  
  177.  LoadFile(filename,buffer,0,0);
  178.  
  179.  GetChunkID(buffer,tempstr);
  180.  if (strcmp(tempstr,"FORM")!=0)
  181.    errout("This isn't an ILBM FORM format file!");
  182.  
  183.   /*
  184.   ** point past the FORM chunk
  185.   ** and see if this really IS
  186.   ** and ILBM file
  187.   */
  188.  
  189.   buffer += 8;
  190.   GetChunkID(buffer,tempstr);
  191.   strcpy(typestr,tempstr); // save file type
  192.   if ((strcmp(tempstr,"ILBM")!=0) && (strcmp(tempstr,"PBM ")!=0) )
  193.     errout("This isn't an ILBM format file!");
  194.  
  195.   /*
  196.   ** point to BMHD chunk, the first NORMAL chunk!
  197.   */
  198.  
  199.   buffer += 4;
  200.   GetChunkID(buffer,tempstr);
  201.   if (strcmp(tempstr,"BMHD")!=0)
  202.     errout("What kind of ILBM is this? There's no BMHD chunk!");
  203.  
  204.   return(buffer);
  205. }
  206.  
  207.  
  208.  
  209. void GetChunkID(char huge *buffer,char *tempstr)
  210. {
  211.   movedata(FP_SEG(buffer),FP_OFF(buffer),_DS,(unsigned)tempstr,4);
  212.   tempstr[4]=0;
  213. }
  214.  
  215.  
  216.  
  217.  
  218. int NextChunkID(char huge *buffer)
  219. {
  220.   unsigned int newoffset;
  221.  
  222.   newoffset = (*(buffer+7)&0xFF) + (*(buffer+6)*256);
  223.   if ((newoffset & 1)==1) newoffset += 1;
  224.   return(newoffset+8); /* +8 because chunk + offset = 8 bytes! */
  225. }
  226.  
  227.  
  228. /////////////////////////////////////////////////////////////
  229. /*
  230. ** CGA loader
  231. */
  232. /////////////////////////////////////////////////////////////
  233. void Do_CGA_Screen(char huge *buffer,char compress,char planes,int width,int height,char huge *scrnmem)
  234. {
  235.  unsigned int bpwidth,loopY,loopX,loopB,offset,data;
  236.  char huge *screen,b1,b2,unpacked[1280];
  237.  
  238.  bpwidth = width/8;
  239.  
  240.  for (loopY=0;loopY<height;loopY++)
  241.      {
  242.       if (compress==1)
  243.      buffer=Decompress(buffer,unpacked,bpwidth,planes);
  244.  
  245.       offset=0;
  246.       screen=scrnmem+(loopY*((width/8)*planes));
  247.       // screen = MK_FP(0xb800,(0x2000*(loopY&1))+(80*(loopY/2)));
  248.       for (loopX=0;loopX<bpwidth;loopX++)
  249.       {
  250.        if (compress==1)
  251.           {
  252.            b1 = *(unpacked+offset);
  253.            b2 = *(unpacked+bpwidth+offset);
  254.           }
  255.        else
  256.           {
  257.            b1 = *(buffer+offset);
  258.            b2 = *(buffer+bpwidth+offset);
  259.           }
  260.        offset++;
  261.  
  262.        // This loop should be in INLINE(!) assembler!
  263.  
  264.                 asm       mov   cx,8
  265.                 asm       mov   bh,b1
  266.                 asm       mov   bl,b2
  267.                 asm       xor   dx,dx
  268.                 LoopTop:
  269.                 asm       test  bh,1
  270.                 asm       jz    NoOR
  271.                 asm       or    dx,4000h
  272.                 NoOR:
  273.                 asm       test  bl,1
  274.                 asm       jz    NoOR1
  275.                 asm       or    dx,8000h
  276.                 NoOR1:
  277.                 asm       cmp   cx,1
  278.                 asm       je    NoShift
  279.                 asm       shr   dx,1
  280.                 asm       shr   dx,1
  281.                 NoShift:
  282.                 asm       shr   bh,1
  283.                 asm       shr   bl,1
  284.                 asm       loop  LoopTop
  285.  
  286.                 asm       mov   data,dx
  287.  
  288.        /* first draft of above loop:
  289.  
  290.            for (loopB=0;loopB<8;loopB++)
  291.                {
  292.                 if (b1 & 1==1) data |= 0x4000;
  293.                 if (b2 & 1==1) data |= 0x8000;
  294.                 if (loopB<7) data >>= 2;
  295.                 b1 >>= 1;
  296.                 b2 >>= 1;
  297.                }
  298.            */
  299.  
  300.            *screen = data >> 8;
  301.            *(screen+1) = data;
  302.            screen += 2;
  303.           }
  304.  
  305.       if (!compress)
  306.          buffer += bpwidth*planes;
  307.      }
  308. }
  309.  
  310.  
  311. /////////////////////////////////////////////////////////////
  312. //
  313. // EGA loader
  314. //
  315. /////////////////////////////////////////////////////////////
  316. void Do_EGA_Screen(char huge *buffer,char compress,char planes,int width,int height,char huge *scrnmem)
  317. {
  318.  unsigned bpwidth,loopY,loopX,loopB,offset,data,dest,j;
  319.  char huge *screen,b1,b2,unpacked[1280], // 8 screens wide max!!!
  320.       huge *plane[4];
  321.  long size;
  322.  
  323.  
  324.  bpwidth = width/8;
  325.  size=bpwidth*height;
  326.  
  327.  plane[0]=scrnmem;
  328.  plane[1]=plane[0]+size;
  329.  plane[2]=plane[1]+size;
  330.  plane[3]=plane[2]+size;
  331.  
  332.  for (loopY=0;loopY<height;loopY++)
  333.      {
  334.       if (compress==1)
  335.      {
  336.       buffer=Decompress(buffer,unpacked,bpwidth,planes);
  337.       dest=loopY*bpwidth;
  338.       for (i=0;i<4;i++)
  339.         {
  340.          movedata(FP_SEG(unpacked+bpwidth*i),
  341.               FP_OFF(unpacked+bpwidth*i),
  342.               FP_SEG(plane[i])+dest/16,
  343.               FP_OFF(plane[i])+(dest&15),
  344.               bpwidth);
  345.         }
  346.      }
  347.       else
  348.      {
  349.       dest=loopY*bpwidth;
  350.       for (i=0;i<4;i++)
  351.         {
  352.          movedata(FP_SEG(buffer+bpwidth*i),FP_OFF(buffer+bpwidth*i),
  353.               FP_SEG(plane[i])+dest/16,FP_OFF(plane[i])+(dest&15),
  354.               bpwidth);
  355.         }
  356.       buffer += bpwidth*planes;
  357.      }
  358.      }
  359. }
  360.  
  361. /////////////////////////////////////////////////////////////
  362. /*
  363. ** MCGA loader
  364. */
  365. /////////////////////////////////////////////////////////////
  366. void Do_MCGA_Screen(char huge *buffer,char compress,int width,int height,char huge *scrnmem)
  367. {
  368.  unsigned int bpwidth,loopY,loopX,loopB,offset,data;
  369.  char huge *screen,b1,b2,unpacked1[1280],unpacked[1280];
  370.  
  371.  
  372.  screen=scrnmem;
  373.  
  374.  for (loopY=0;loopY<height;loopY++)
  375.      {
  376.       if (compress==1)
  377.          {
  378.       buffer=Decompress(buffer,unpacked,width,1);
  379.       if (strcmp(typestr,"ILBM")==0)
  380.          {
  381.           int tloop;
  382.  
  383.           memset(unpacked1,0,320);
  384.           for (tloop=0;tloop<40;tloop++)
  385.           {
  386.            int tloop1,tloop2;
  387.            unsigned char mask[8] = { 0x80,0x40,0x20,0x10,8,4,2,1 };
  388.  
  389.            for (tloop1=0;tloop1<8;tloop1++)
  390.              for (tloop2=0;tloop2<8;tloop2++)
  391.                unpacked1[tloop*8+tloop1]|=
  392.               ((( (unsigned)unpacked[tloop+(7-tloop2)*40]
  393.               &mask[tloop1])
  394.               <<tloop1)
  395.               >>tloop2);
  396.           }
  397.           movedata(_DS,(unsigned)unpacked1,FP_SEG(screen),FP_OFF(screen),width);
  398.          }
  399.       else movedata(_DS,(unsigned)unpacked,FP_SEG(screen),FP_OFF(screen),width);
  400.          }
  401.       else
  402.          {
  403.       movedata(FP_SEG(buffer),FP_OFF(buffer),FP_SEG(screen),FP_OFF(screen),width);
  404.           buffer += width;
  405.          }
  406.       screen+=width;
  407.      }
  408. }
  409.  
  410. /////////////////////////////////////////////////////////////
  411. /*
  412. ** ILBM's RLE decompressor. Merely pass the address of the compressed
  413. ** ILBM bitplane data, where to unpack it, the # of bytes each bitplane
  414. ** takes up, and the # of bit planes to unpack.
  415. */
  416. /////////////////////////////////////////////////////////////
  417. void huge *Decompress(char huge *buffer,char *unpacked,int bpwidth,char planes)
  418. {
  419.  int count,offset,loopP;
  420.  unsigned char byte,rept;
  421.  
  422.  #if 0
  423.  for (loopP=0;loopP<planes;loopP++)
  424.      {
  425.       count = 0;
  426.  
  427.       do {
  428.           rept = *(buffer);
  429.           if (rept > 0x80)
  430.              {
  431.               rept = (rept^0xff)+2;
  432.               byte = *(buffer+1);
  433.               buffer+=2;
  434.  
  435.               memset(unpacked,byte,rept);
  436.              }
  437.           else if (rept < 0x80)
  438.              {
  439.           rept++;
  440.           movedata(FP_SEG(buffer),FP_OFF(buffer)+1,_DS,(unsigned) unpacked,rept);
  441.           buffer += rept+1;
  442.              }
  443.           count += rept;
  444.           unpacked += rept;
  445.  
  446.          } while (count<bpwidth);
  447.      }
  448.  #else
  449.  
  450.  unsigned PackHi,PackLo,BufHi,BufLo;
  451.  
  452.  PackHi=FP_SEG(unpacked);
  453.  PackLo=FP_OFF(unpacked);
  454.  BufHi=FP_SEG(buffer);
  455.  BufLo=FP_OFF(buffer);
  456.  
  457.  asm    push    di
  458.  asm    push    si
  459.  asm    push    ds
  460.  
  461.  asm    mov    es,PackHi
  462.  asm    mov    di,PackLo
  463.  asm    mov    ds,BufHi
  464.  asm    mov    si,BufLo
  465.  asm    mov    cl,planes
  466.  asm    xor    ch,ch
  467.  asm    xor    ah,ah
  468.  LOOP1:
  469.  asm    push    cx
  470.  asm    xor    dx,dx        // DX = count
  471.  
  472.  LOOP2:
  473.  asm    lodsb
  474.  asm    cmp    al,0x80
  475.  asm    jbe    L2
  476.  asm    xor    al,0xff        // rept^0xff
  477.  asm    add    al,2        // rept+=2
  478.  asm    add    dx,ax
  479.  asm    mov    cl,al
  480.  asm    xor    ch,ch
  481.  asm    lodsb                // AL=byte to rept
  482.  asm    rep stosb        // repeat it!
  483.  asm    jmp    L3
  484.  
  485.  L2:
  486.  asm    inc    al
  487.  asm    add    dx,ax
  488.  asm    mov    cl,al
  489.  asm    xor    ch,ch
  490.  asm    rep movsb
  491.  
  492.  L3:
  493.  asm    cmp    dx,bpwidth
  494.  asm    jb    LOOP2
  495.  
  496.  asm    pop    cx
  497.  asm    loop    LOOP1
  498.  
  499.  asm    mov    PackHi,es
  500.  asm    mov    PackLo,di
  501.  asm    mov    BufHi,ds
  502.  asm    mov    BufLo,si
  503.  
  504.  asm    pop    ds
  505.  asm    pop    si
  506.  asm    pop    di
  507.  
  508.  buffer=MK_FP(BufHi,BufLo);
  509.  unpacked=(char *)PackLo;
  510.  #endif
  511.  
  512.  return(buffer);
  513. }
  514.  
  515.  
  516. #if 0
  517. /////////////////////////////////////////////////////////////
  518. //
  519. // move an EGA bitplane
  520. //
  521. /////////////////////////////////////////////////////////////
  522. void EGA_MoveBitplane(char huge *from,char far *to,int bpwidth)
  523. {
  524.  unsigned width;
  525.  
  526. asm        push    ds
  527. asm        push    di
  528. asm        push    si
  529.  
  530. asm        lds    si,from        //;DS:SI = from buffer
  531. asm        les    di,to        //;ES:DI = screen
  532. asm        mov    bx,bpwidth
  533. asm        mov    width,bx
  534.  
  535. asm        mov    dx,SCindex    //;start writing to SCmapmask register
  536. asm        mov    al,SCmapmask
  537. asm        out    dx,al
  538. asm        inc    dx
  539.  
  540. asm        mov    bh,4        //;4 bitplanes!
  541. asm        mov    ah,1        //;start at bitplane 0
  542.  
  543. EGA1:
  544.  
  545. asm        mov    al,ah        //;select bitplane
  546. asm        out    dx,al
  547.  
  548. asm        xor    ch,ch
  549. asm        mov    cl,bl        //;cx = bitplane width
  550. asm        rep movsb
  551. asm        sub    di,width    //;start at beginnin' of line again...
  552. asm        shl    ah,1
  553. asm        dec    bh
  554. asm        jnz    EGA1
  555.  
  556. asm        mov    al,15
  557. asm        out    dx,al        //;write to ALL bitplanes again
  558.  
  559. asm        pop    si
  560. asm        pop    di
  561. asm        pop    ds
  562. }
  563. #endif
  564.  
  565.  
  566.